# coding: utf-8
'''
Description: Jenkins Job管理
version: 1.0.0
Author: peng2.zhang
Date: 2020-09-30 16:45:51
LastEditors: peng2.zhang
LastEditTime: 2022-05-07 16:17:48
'''
import time
import base64
import urllib
import urllib3
import jenkins
from ci_conclude.const import JenkinsServer
urllib3.disable_warnings()


class JenkinsManage():
    retry_max_num = 3
    retry_sleep = 60
    def retry_jenkins(self, num=0):
        '''
            检查Jenkins服务是否可用，如果不可用，重试3次
        '''
        if num >= self.retry_max_num: 
            self.j = None
            return False
        try:
            print("retry_jenkins")
            # self.j = jenkins.Jenkins(self.jenkins_server, username=self.username, password=self.password)
            _info = self.get_job_info(self.job_name)
        except Exception as e:
            print(f"sleep {self.retry_sleep} -- retry {num+1}")
            time.sleep(self.retry_sleep)
            self.retry_jenkins(num=num+1)

    def __init__(self, jenkins_server=JenkinsServer.DEFAULT.NAME, url_path="/view/ops/job/", job_name="admapci_ad-compare-diff-app-meta", username="", password=""):
        self.jenkins_server = jenkins_server
        self.url_path = url_path
        self.job_name = job_name
        self.username = base64.b64decode(username).decode()
        self.password = base64.b64decode(password).decode()
        self.j = jenkins.Jenkins(self.jenkins_server, username=self.username, password=self.password)
        # self.retry_jenkins()
    
    def get_job_info(self, job_name):
        if not hasattr(self, f"_job_info_{job_name}"):
            job_info = self.j.get_job_info(job_name)
            setattr(self, f"_job_info_{job_name}", job_info)
        return getattr(self, f"_job_info_{job_name}")
    
    def get_build_info(self, job_name, buildid):
        try:
            if not hasattr(self, "_build_info"):
                build_info = self.j.get_build_info(job_name, int(buildid))
                setattr(self, "_build_info", build_info)
            return getattr(self, "_build_info")
        except Exception as e:
            print(e)
            # from code import interact
            # interact(local=locals())

    def get_job_description(self, job_name):
        job_info = self.get_job_info(job_name)
        description = job_info["description"]
        return description
    
    def get_build_username(self, job_name, buildid):
        build_info = self.get_build_info(job_name, buildid)
        # from code import interact
        # interact(local=locals())
        # cause = build_info["actions"][1]["causes"][0]
        build_causes = [i for i in build_info["actions"] if "causes" in i]
        if build_causes:
            causes = build_causes[0]["causes"]
            cause = causes[0]
        else:
            cause = {}
        username = cause.get("userId") or cause.get("shortDescription")
        return username

    def job_start(self, job_name, job_param_dict={}, **kwargs):
        """
            启动job
            job_name：job名称，如：ops_gemini-autobuildtestline
            job_param_dict：job参数，已python字典方式传入
        """
        self.job_name = job_name
        self.job_param_dict = job_param_dict

        # 检查job_name的构建信息，如果有正在构建的任务，就等待
        job_info = self.j.get_job_info(job_name)
        # print(job_info)
        lastBuildNum = job_info["lastBuild"]["number"]
        nextBuildNum = job_info["nextBuildNumber"]
        lastBuildStatus = self.j.get_build_info(job_name, lastBuildNum)["result"]
        if not lastBuildStatus:
            # 等待上次构建的任务执行结束
            self.check_job_status(job_name, buildid=lastBuildNum, job_param_dict=job_param_dict)
        
        # queue_list = self.j.get_queue_info()
        # 检查是否有排队的任务，如果有正在排队的任务，等待排队的任务执行完
        self.check_job_queue()
        
        # 开始构建任务
        build_job = self.j.build_job(job_name, parameters=job_param_dict)
        job_info2 = self.j.get_job_info(job_name)
        # from code import interact
        # interact(local=locals())
        # if job_info2["lastBuild"]["number"] == nextBuildNum:
        self.check_job_status(job_name, buildid=nextBuildNum, job_param_dict=job_param_dict, **kwargs)
    
    def check_job_status(self, job_name, buildid, job_param_dict={}, **kwargs):
        """
            轮询job的状态
        """
        print("===== check job status =====")
        duration = self.job_duration(buildid-1)
        while self.job_status(job_name, buildid, job_param_dict) in ["RUNNING", "UNKNOWN"]:
            time.sleep(5)
        self.job_status(job_name, buildid, job_param_dict=job_param_dict, **kwargs)

    def job_status(self, job_name, buildid="lastBuild", job_param_dict={}):
        """
            获取job的状态
        """
        job_info = self.j.get_job_info(job_name)
        # print(job_info)
        if buildid == "lastBuild":
            buildNum = job_info["lastBuild"]["number"]
        else:
            buildNum = int(buildid)
        # print("")
        try:
            buildStatus = self.j.get_build_info(job_name, buildNum)["result"]
            _job_status = "RUNNING" if not buildStatus else buildStatus
            print(f"===== build_id: {buildid} status: [{_job_status}] job_name: {job_name} =====")
            # if _job_status == "FAILURE":
            #     self.failure_result(job_name, buildid, job_param_dict, **kwargs)
        except Exception as e:
            _job_status = "UNKNOWN"
        return _job_status
    
    def job_duration(self, job_name, buildid="lastBuild", job_param_dict={}):
        job_info = self.j.get_job_info(job_name)
        # print(job_info)
        if buildid == "lastBuild":
            buildNum = job_info["lastBuild"]["number"]
        else:
            buildNum = int(buildid)
        # print("")
        buildInfo = self.j.get_build_info(job_name, buildNum)
        duration = int(buildInfo["duration"] / 1000)
        minutes = int(duration/60)
        seconds = int(duration%60)
        print('duration (M:S) = ' + str(minutes) + ':' + str(seconds))
        return duration
        # return f"{str(minutes)}m:{str(seconds)}s"

    def check_job_queue(self):
        """
            轮询job的排队状态
        """
        print("===== check job queue =====")
        while len(self.job_queue()) > 0:
            time.sleep(5)

    def job_queue(self):
        """
            获取job的排队状态
        """
        queue_list = self.j.get_queue_info()
        print(f"===== job queue len: {len(queue_list)} =====")
        return queue_list

    # def job_result(self, buildid="lastBuild"):
    #     """
    #         获取job的结果
    #     """
    #     print("{}/view/ops/job/{}/{}/allure/".format(self.jenkins_server, self.job_name, buildid))

